<?php

namespace App\Http\Controllers\Admin;

use App\Enums\AssetSourceType;
use App\Enums\AssetStatus;
use App\Enums\ProductType;
use App\Enums\TokenLockType;
use App\Enums\TokenStatus;
use App\Http\Controllers\Controller;
use App\Models\Airdrop;
use App\Models\Asset;
use App\Models\FrontendUser;
use App\Models\Product;
use App\Models\ProductToken;
use App\Services\WalletService;
use Illuminate\Support\Arr;
use Vinlon\Laravel\LayAdmin\Exceptions\AdminException;

class AirdropController extends Controller
{
    /** @var WalletService */
    private $walletService;

    /**
     * Create the event listener.
     */
    public function __construct(WalletService $walletService)
    {
        $this->walletService = $walletService;
    }

    /**
     * 获取空投记录.
     *
     * @return mixed
     */
    public function index()
    {
        $query = Airdrop::query()
            ->with('agent')
            ->where('type', ProductType::ISSUE)
            ->when(request()->keyword, function ($q) {
                return $q->where(function ($q1) {
                    $likeVal = '%' . request()->keyword . '%';

                    return $q1->where('nickname', 'like', $likeVal)->orWhere('mobile', 'like', $likeVal)->orWhere('goods_name', 'like', $likeVal);
                });
            })
            ->when(request()->status, function ($q) {
                if (3 == request()->status) {
                    request()->status = 0;
                }

                return $q->where('status', request()->status);
            })
            ->when(request()->agent_id, function ($q) {
                return $q->where('agent_id', request()->agent_id);
            })
            ->orderByDesc('id');

        return paginate_result($query);
    }

    public function reissue($id)
    {
        $airdrop = $this->findAirdropOrFail($id);

        $goods = Product::where('id', $airdrop->goods_id)->where('agent_id', $airdrop->agent_id)->first();

        if (empty($goods)) {
            throw new AdminException('空投未找到');
        }

        $contractAddress = $goods->contract_address;
        $quantity = 1;
        $tokens = ProductToken::query()->where('product_id', $goods->id)
            ->where('status', TokenStatus::INIT)
            ->limit($quantity)->get();

        $productTokenIds = Arr::pluck($tokens, 'id');
        $tokenIds = Arr::pluck($tokens, 'token_id');

        if (count($tokenIds) < $quantity) {
            $airdrop->status = 2;
            $airdrop->error_msg = '库存不足';
            $airdrop->save();

            throw new AdminException('库存不足');
        }

        $airdrop->tokenIds = json_encode($tokenIds);

        // 锁定
        ProductToken::query()->whereIn('id', $productTokenIds)->update([
            'lock_type' => TokenLockType::AIRDROP,
            'lock_refer_id' => $airdrop->id,
            'status' => TokenStatus::LOCKED,
        ]);

        $user = FrontendUser::where('mobile', $airdrop->mobile)->where('agent_id', $airdrop->agent_id)->first();

        try {
            $fromMobile = ''; // 默认使用商品发布时的收款方为付款方
            if ($goods->resale_user) {
                $fromMobile = $goods->resale_user->mobile;
            }
            $transResult = $this->walletService->transfer(
                $fromMobile,
                $contractAddress,
                $tokenIds,
                $user->wallet_address
            );
            // 更新token状态
            foreach ($tokens as $token) {
                $transHash = Arr::get($transResult, $token->token_id, 'trans_hash_not_return');
                $token->status = TokenStatus::SOLD;
                $token->save();

                // 保存资产信息
                $asset = new Asset();
                $asset->user_id = $user->id;
                $asset->source_type = AssetSourceType::AIRDROP;
                $asset->source_id = $airdrop->id;
                $asset->contract_address = $goods->contract_address;
                $asset->token_id = $token->token_id;
                $asset->trans_hash = $transHash;
                $asset->asset_status = AssetStatus::HOLD;
                $asset->save();
            }
            $airdrop->status = 1;
            $airdrop->save();
        } catch (\Exception $e) {
            ProductToken::query()->whereIn('id', $productTokenIds)->update([
                'status' => TokenStatus::FAILED,
            ]);

            $airdrop->status = 2;
            $airdrop->error_msg = $e->getMessage();
            $airdrop->save();

            throw new AdminException($e->getMessage());
        }
    }

    private function findAirdropOrFail($id)
    {
        /** @var AgentUser $user */
        $user = auth()->user();
        $airdrop = Airdrop::where('agent_id', $user->agent_id)
            ->find($id);
        if (!$airdrop) {
            throw new AdminException('空投未找到');
        }

        return $airdrop;
    }
}
